/**
 * SSP for APP
 * Copyright 2013 Baidu Inc. All rights reserved.
 *
 * @ignore
 * @file 表格行拖拽排序扩展
 * @author otakustay
 */
define(
    function (require) {
        var u = require('common/util');
        var lib = require('esui/lib');

        var exports = {};

        exports.type = 'TableDragSort';

        exports.constructor = function () {
            this.$super(arguments);

            u.bindAll(this, 'startDrag', 'moveRow', 'finishDrag');
        };

        exports.findRowElement = function (from) {
            var row = from;
            while (row && !this.target.helper.isPart(row, 'row')) {
                row = row.parentNode;
            }

            return row;
        };

        exports.getRows = function () {
            var body = this.target.helper.getPart('body');
            var rows = body.querySelectorAll('.' + this.target.helper.getPartClasses('row')[0]);
            return rows;
        };

        // 获取能够拖拽的行数
        exports.getDraggableRows = function () {
            var rows = this.getRows();
            var result = 0;
            for (var i = 0; i < rows.length; i++) {
                if (rows[i].querySelectorAll('.' + this.dragZone).length) {
                    result++;
                }
                else {
                    return result;
                }
            }
            return result;
        };

        exports.swapRow = function (target) {
            if (target === this.row) {
                return;
            }

            var theRowNextToDraggingOne = this.row.nextSibling;
            var theRowNextToSwapTarget = target.nextSibling;
            var parent = this.row.parentNode;
            parent.insertBefore(target, theRowNextToDraggingOne);
            parent.insertBefore(this.row, theRowNextToSwapTarget);
        };

        exports.updateDatasource = function () {
            var datasource = this.target.get('datasource');
            var sortedDatasource = u.map(
                this.getRows(),
                function (row) {
                    var index = lib.getAttribute(row, 'data-index');
                    return datasource[index];
                }
            );
            u.each(
                sortedDatasource,
                function (item, i) {
                    datasource[i] = item;
                }
            );
        };

        exports.isDragZone = function (element) {
            var className = this.dragZone || this.target.helper.getPartClasses('row')[0];
            while (element) {
                if (lib.hasClass(element, className)) {
                    return true;
                }
                element = element.parentNode;
            }
            return false;
        };

        exports.startDrag = function (e) {
            // 不是左键的直接忽略
            var button = e.which || e.button;
            if (button !== 1) {
                return;
            }

            if (this.row) {
                return;
            }

            if (!this.isDragZone(e.target)) {
                return;
            }

            this.row = this.findRowElement(e.target);

            if (!this.row) {
                return;
            }

            var table = this.target;
            var body = table.helper.getPart('body');

            this.phantom = this.row.cloneNode(true);
            this.initialY = e.clientY;
            this.initialTop = lib.getOffset(this.row).top - lib.getOffset(body).top;
            this.rowHeight = this.row.offsetHeight;
            this.bodyHeight = body.offsetHeight;

            // 可允许在前几行拖拽。
            var draggableRows = this.getDraggableRows();

            this.draggableBoundry = {
                begin: 0,
                end: (draggableRows - 1) * this.rowHeight
            };

            table.helper.addPartClasses('row-dragging', this.row);

            this.phantom.id = '';
            // 要去掉什么`row-odd`、`row-hover`之类的，仅保留最基本的2个样式
            this.phantom.className = table.helper.getPartClassName('row')
                + ' ' + table.helper.getPartClassName('row-dragging-phantom');
            this.phantom.style.top = this.initialTop + 'px';
            body.appendChild(this.phantom);

            table.helper.addDOMEvent(document.documentElement, 'mousemove', this.moveRow);
            table.helper.addDOMEvent(document.documentElement, 'mouseup', this.finishDrag);

            table.helper.addPartClasses('dragging');
        };

        exports.moveRow = function (e) {
            if (!this.row) {
                return;
            }

            var offsetTop = this.initialTop + (e.clientY - this.initialY);
            // 控制只能在表格体的范围内
            if (offsetTop < this.draggableBoundry.begin) {
                offsetTop = this.draggableBoundry.begin;
            }
            else if (offsetTop > this.draggableBoundry.end) {
                offsetTop = this.draggableBoundry.end;
            }
            this.phantom.style.top = offsetTop + 'px';

            // 算一下被拖动的元素的顶边在哪两行的中线之间
            var rows = this.getRows();
            for (var i = 0; i < rows.length; i++) {
                // 实际算的是“上一行的中线和当前行的中线之间”，即第1行的时候`i`为`-1`
                var previousMiddleLineTop = (i - 1) * this.rowHeight + this.rowHeight / 2;
                var currentMiddleLineTop = previousMiddleLineTop + this.rowHeight;
                if (previousMiddleLineTop < offsetTop && currentMiddleLineTop > offsetTop) {
                    this.swapRow(rows[i]);
                }
            }
        };

        exports.finishDrag = function () {
            if (!this.row) {
                return;
            }

            var table = this.target;
            table.helper.removeDOMEvent(document.documentElement, 'mousemove', this.moveRow);
            table.helper.removeDOMEvent(document.documentElement, 'mouseup', this.finishDrag);

            lib.removeNode(this.phantom);
            table.helper.removePartClasses('row-dragging', this.row);

            this.row = null;
            this.phantom = null;

            this.updateDatasource();
            this.updateView();
            table.fire('dragsortend');
        };

        exports.updateView = function () {
            this.target.helper.removePartClasses('dragging');
            this.target.setDatasource(this.target.get('datasource'));
        };

        exports.activate = function () {
            this.$super(arguments);

            var table = this.target;
            table.helper.addDOMEvent(table.main, 'mousedown', this.startDrag);
        };

        var TableDragSort = require('eoo').create(require('esui/Extension'), exports);
        require('esui').registerExtension(TableDragSort);
        return TableDragSort;
    }
);
